package gbench.sandbox.record;

import org.junit.jupiter.api.Test;

import java.util.Date;
import java.util.UUID;
import java.time.LocalDate;
import java.time.LocalDateTime;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import static gbench.common.tree.LittleTree.IRecord.REC;
import static gbench.common.tree.LittleTree.*;

/**
 * 看我72變:IRecord 作为一种中间结构拥有无穷的变化能力
 * @author gbench
 *
 */
public class JunitRecordMutate {
    
    @Data @AllArgsConstructor @NoArgsConstructor 
    public static class User{
        
        /**
         * 构造函数
         * @param name
         */
        public User(final String name) {
            this.name = name;
        }
        
        private String id = UUID.randomUUID().toString();
        private String name;
        private String address;
        private LocalDate birth;
        private User leader ;// 领导
    }
    
    /**
     * 一个概念 就像一个 思想蛋白,使用  static 确保这是一个 可以被 进行反射 来构造对象实例的类对象。 
     * @author gbench
     *
     */
     @Data @NoArgsConstructor
     public final static class Product{
         private Integer id;
         private String name;
         private LocalDateTime date;
     }
     
     /**
      * 一个概念 就像一个 思想蛋白,使用  static 确保这是一个 可以被 进行反射 来构造对象实例的类对象。 
      * 订单的类型
      * @author gbench
      *
      */
     @Data @NoArgsConstructor
     public final static class Order{
         private User user;
         private Product product;
         private double price;
     }
    
    @Test
    public void foo() {
        final var zhangsan = REC("id",1,"name","張三","birth","1985-09-23"); // 会生成一个 默认领导对象。注意领导对象leader属性不为null,但是address属性为null
        System.out.println("mutate 轉換的 結果:leader 为空"+zhangsan.mutate(User.class));
        System.out.println("mutate 轉換的 結果:Leader 不为空"+zhangsan.mutate(User.class,true));
        System.out.println("mutate2 轉換的 結果(整數轉換成字符串的時候出錯了)"+zhangsan.mutate2(User.class));
    }
    
    @Test
    public void bar() {
        System.out.println("long:"+REC("a",'a',"b",8,"c",123).toTarget(Long.class));// 8
        System.out.println("double:"+REC("a",'a',"b",8,"c",123).toTarget(Double.class));// 8
        System.out.println("short:"+REC("a",'a',"b",8,"c",123).toTarget(short.class));// 8
        System.out.println("Character 1:"+REC("a",'a',"b",8,"c",123).toTarget(Character.class));// 8
        System.out.println("char 2:"+REC("a","a","b",8,"c",123).toTarget(char.class));//  原因是 把a视byte而后再转换成字符char
        System.out.println("byte:"+REC("a","a","b",8,"c",123).toTarget(byte.class));// 8
        System.out.println("String:"+REC("a","a","b",8,"c",123).toTarget(String.class));// a
        System.out.println("Float:"+REC("a","a","b",8,"c",123).toTarget(Float.class));// 8。0
        System.out.println("Date 1:"+REC("a",'a',"b",8,"c",123,"d",new Date()).toTarget(Date.class));// 8
        System.out.println("Date 2:"+REC("a",'a',"b",8,"c",123,"d",new Date()).toTarget(LocalDateTime.class));// 8
        System.out.println("Date 3:"+REC("a",'a',"b",8,"c",123,"d",LocalDateTime.now()).toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 1:"+REC("a",'a',"b",8,"c",123,"d","1989").toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 2:"+REC("a",'a',"b",8,"c",123,"d","1989-09").toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 3:"+REC("a",1,"b","1989-09-11 11:23").toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 4:"+REC("b","1989").toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 5:"+REC("b","1989-09").toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 6:"+REC("b","1989-09-11").toTarget(LocalDateTime.class));// 8
        System.out.println("LocalDateTime 7:"+REC("b","1989-09-11 11:23").toTarget(LocalDateTime.class));// 8
        
        // toTarget 与 mutate 拥有类似功能 但稍微有点不同。 
        final var t = REC("a","a","b",8,"c",123).toTarget(Integer.class);// 8
        System.out.println("Integer:"+t);
        final var t1 = REC("a","a","b",8,"c",123).mutate(int.class);// 8
        System.out.println("int:"+t1);
        
        final var t2 = REC("a","a","b",8,"c",123).mutate(Integer.class);// 8
        System.out.println("Integer："+t2);
        
        final var b = REC("a","a","b",8,"c",123).toTarget(Boolean.class); // true
        System.out.println("Boolean"+b);
        final var b1 = REC().toTarget(Boolean.class); // false
        System.out.println("Boolean:"+b1);
    }
    
    /**
     * 这是一个递归创建数据结构的办法
     */
    @Test
    public void qux() {
       final var rec = REC( // 设置一个 IRecord 结构化出的 符合的Order的对象 
           "user",REC("id",1,"name","张三","address","上海市长宁区法华镇路101弄11#201","birth",LocalDateTime.now()),
           "product",REC("id",1,"name","葡萄","date",LocalDateTime.now()),
           "price",REC("value",25)); 
       final var order = rec.mutate(Order.class); // 生成一个复合的结构
       System.out.println(MFT("\norder对象的重新构造:\n{0}",order));
       System.out.println(MFT("product-date:{0}",order.getProduct().getDate()));// 获得order的产品各个深层属性
    }

}
